package com.da.javatest.thread.juc;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author chenlida
 * @date 2020/7/9 15:23
 * @description 可中断死锁
 *
 * 1.ReentrantLock可以实现公平锁和非公平锁
 *
 * 2.ReentrantLock默认实现的是非公平锁
 *
 * 3.ReentrantLock的获取锁和释放锁必须成对出现，锁了几次，也要释放几次
 *
 * 4.释放锁的操作必须放在finally中执行
 *
 * 5.lockInterruptibly()实例方法可以相应线程的中断方法，调用线程的interrupt()方法时，lockInterruptibly()
 * 方法会触发 InterruptedException异常
 *
 * 6.关于 InterruptedException异常说一下，看到方法声明上带有 throwsInterruptedException，表示该方法可以相应线程中断，
 * 调用线程的interrupt()方法时，这些方法会触发InterruptedException异常，触发InterruptedException时，
 * 线程的中断中断状态会被清除。所以如果程序由于调用 interrupt()方法而触发InterruptedException异常，
 * 线程的标志由默认的false变为ture，然后又变为false
 *
 * 7.实例方法tryLock()获会尝试获取锁，会立即返回，返回值表示是否获取成功
 *
 * 8.实例方法tryLock(long timeout, TimeUnit unit)会在指定的时间内尝试获取锁，指定的时间内是否能够获取锁，都会返回，
 * 返回值表示是否获取锁成功，该方法会响应线程的中断
 */
public class ReentrantLockDeadLock {
    private static ReentrantLock lock1 = new ReentrantLock(false);
    private static ReentrantLock lock2 = new ReentrantLock(false);

    public static class MyThread extends Thread {
        int lock;

        public MyThread(String name, int lock) {
            super(name);
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                if (this.lock == 1) {
                    lock1.lockInterruptibly();
                    TimeUnit.SECONDS.sleep(1);
                    lock2.lockInterruptibly();
                } else {
                    lock2.lockInterruptibly();
                    TimeUnit.SECONDS.sleep(1);
                    lock1.lockInterruptibly();
                }
            } catch (InterruptedException e) {
                System.out.println("中断标志:" + this.isInterrupted());
                e.printStackTrace();
            } finally {
                if (lock1.isHeldByCurrentThread()) {
                    lock1.unlock();
                }
                if (lock2.isHeldByCurrentThread()) {
                    lock2.unlock();
                }
            }
        }

    }

    public static void main(String[] args) throws InterruptedException {
        MyThread t1 = new MyThread("t1", 1);
        MyThread t2 = new MyThread("t2", 2);

        t1.start();
        t2.start();

        // 解锁
        TimeUnit.SECONDS.sleep(3);
        t1.interrupt();
    }
}
